#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QRegularExpression>
#include <QDateTime>
#include <QMessageBox>
#include <QJsonDocument>
#include <QJsonObject>
#include <QValueAxis>
#include <csignal>  // 添加这个头文件
#include <QNetworkInterface>  // 网络接口相关
#include <QHostAddress>       // IP地址处理
#include <QDebug>

/*void MainWindow::handleFrameDone(const QString &response)
{
    //hwStatus.cameraState = MainWindow::Idle;
    QStringList parts = response.split(':');
    QString tag;

    foreach (const QString &part, parts) {
        if (part.startsWith("done=")) {
            tag = part.mid(5);
            break;
        }
    }

    if (tag.isEmpty()) {
        LOG_CAMERA("Invalid task ID");
        return;
    }

    // 记录收到的tag
    m_receivedTags.insert(tag);

    // 检查是否收到所有4个tag（00,01,02,03）
    if (m_receivedTags.size() == 4) {
        // 准备FITS头信息
        std::vector<std::pair<std::string, std::string>> keywords = collectManualHeaderInfo();

    // 如果当前曝光信息匹配，添加时间戳关键字
        //if (m_currentExpInfo.isValid()) {
        // 计算曝光时间（秒）
            double expTime = m_currentExpInfo.expStart.msecsTo(m_currentExpInfo.expEnd) / 1000.0;

        // 添加时间戳关键字
            //keywords.emplace_back("EXPSTART", m_currentExpInfo.expStart.toString("yyyy-MM-ddThh:mm:ss.zzz").toStdString());
            //keywords.emplace_back("EXPEND", m_currentExpInfo.expEnd.toString("yyyy-MM-ddThh:mm:ss.zzz").toStdString());
            //keywords.emplace_back("READOUTS", m_currentExpInfo.readoutStart.toString("yyyy-MM-ddThh:mm:ss.zzz").toStdString());
           // keywords.emplace_back("EXPTIME", QString::number(expTime, 'f', 3).toStdString());

            //LOG_CAMERA(QString("ADD TO FITS HEADER: EXPSTART=%1, EXPEND=%2, READOUTS=%3, EXPTIME=%4")
                     //  .arg(m_currentExpInfo.expStart.toString("yyyy-MM-dd hh:mm:ss.zzz"))
                       //.arg(m_currentExpInfo.expEnd.toString("yyyy-MM-dd hh:mm:ss.zzz"))
                       //.arg(m_currentExpInfo.readoutStart.toString("yyyy-MM-dd hh:mm:ss.zzz"))
                     //  .arg(expTime));
      //  }

        // 使用QtConcurrent并行处理4个bin文件
        QList<QFuture<bool>> futures;
        QStringList fitsFilePaths;

        for (const QString &receivedTag : m_receivedTags) {
            QString binFile = QString("%1/%2.bin").arg(binPath).arg(receivedTag);
            QString fitsFile = fitsSavePath + "/" + currentBaseFilename + "_" + receivedTag + ".fits";
            fitsFilePaths.append(fitsFile);

            futures.append(QtConcurrent::run([this, binFile, receivedTag, keywords]() {
                return convertBinToFits(binFile, fitsSavePath,
                                        currentBaseFilename + "_" + receivedTag,
                                        keywords);
            }));
        }

        // 等待所有转换完成
        for (auto &future : futures) {
            future.waitForFinished();
        }

        // 检查所有FITS文件是否生成成功
        bool allFilesExist = true;
        for (const QString &fitsFile : fitsFilePaths) {
            if (!QFile::exists(fitsFile)) {
                allFilesExist = false;
                LOG_CAMERA(QString("The FITS file has not been generated: %1").arg(fitsFile));
                break;
            }
        }

        // 如果所有FITS文件都存在，则合并它们
        if (allFilesExist) {
            QString mergedFitsPath = fitsSavePath + "/" + currentBaseFilename;
            if(!m_currentExpInfo.isManual && m_pendingResponse.isValid()){
                auto& pending = m_pendingResponse;
                QString doneResponse = QString(
                                           "<ID=302><CamID=%1><TIME=%2><SHUTSTA=closed>"
                                           "<EXPST_TIME=%3><CUR_TEM=%4><INFO=OK><ACTION=DONE>"
                                           "<SENDTIME=%5><FITS_Name=%6>;")
                                           .arg(pending.camId)
                                           .arg(pending.expTime, 0, 'f', 2)
                                           .arg(pending.expStartTimeStr)
                                           .arg(hwStatus.currentTemp, 0, 'f', 2)
                                           .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz"))
                                           .arg(pending.imageName);

                sendResponse(doneResponse, pending.client);
                LOG_CAMERA(QString("Remote Exp completed. [Cam:%1][Tag:%2]").arg(pending.camId).arg(tag));
            }
            if (mergeFitsFiles(fitsFilePaths, mergedFitsPath)) {
                LOG_CAMERA(QString("mergeFitsFiles successfully: %1").arg(mergedFitsPath));
                recordShootingHistory(mergedFitsPath, fitsSavePath); // 记录历史

                // 可选：删除原始单个FITS文件
                for (const QString &fitsFile : fitsFilePaths) {
                    QFile::remove(fitsFile);
                }
            } else {
                LOG_CAMERA("mergeFitsFiles failed");
            }
        }
        QString mergedFitsPath1 = fitsSavePath + "/" + currentBaseFilename;
        QMetaObject::invokeMethod(this, [this, mergedFitsPath1]() {
            if (ui->checkboxShowFits->isChecked()) {
                launchDS9(mergedFitsPath1);
            }
        }, Qt::QueuedConnection);

        m_currentExpInfo = ExposureInfo();

        cameraState.status = 0;
        // 清空已接收的tag
        m_receivedTags.clear();
        PendingResponse pendingResponse;
        m_pendingResponse = pendingResponse;

        // 如果是序列拍摄模式，则继续下一个任务
        if (isSequenceRunning) {
            QTimer::singleShot(1000, this, &MainWindow::processSequenceNextFrame);
        }
        // 如果是循环模式且未完成，启动下一次拍摄
        if (ui->loopCheckBox->isChecked()){
            static int currentLoop = 0;
            static int totalLoops = 1;

            if(currentLoop > 0 && currentLoop < totalLoops) {
                 QTimer::singleShot(1000, this, &MainWindow::on_btnStartExposure_clicked);
            } else {
                currentLoop = 0;
                ui->labelProgressStatus->setText("准备就绪");
            }
        }
    }
}*/

// handleFrameDone函数:支持python转换方式
/*void MainWindow::handleFrameDone(const QString &response)
{
    QStringList parts = response.split(':');
    QString tag;

    foreach (const QString &part, parts) {
        if (part.startsWith("done=")) {
            tag = part.mid(5);
            break;
        }
    }

    if (tag.isEmpty()) {
        LOG_CAMERA(" 无效的任务标识");
        return;
    }
    binPath = "/home/csst/PS_mosaic/data/bin_tmp";
    QString binFile = QString("%1/%2.bin").arg(binPath).arg(tag);
    //QString fitsFile = QString("%1/%2.fits").arg(fitsSavePath).arg(tag);

    std::vector<std::pair<std::string, std::string>> keywords = collectManualHeaderInfo();

    // 如果当前曝光信息匹配，添加时间戳关键字
    if (m_currentExpInfo.isValid()) {
        // 计算曝光时间（秒）
        double expTime = m_currentExpInfo.expStart.msecsTo(m_currentExpInfo.expEnd) / 1000.0;

        // 添加时间戳关键字
        keywords.emplace_back("EXPSTART", m_currentExpInfo.expStart.toString("yyyy-MM-ddThh:mm:ss.zzz").toStdString());
        keywords.emplace_back("EXPEND", m_currentExpInfo.expEnd.toString("yyyy-MM-ddThh:mm:ss.zzz").toStdString());
        keywords.emplace_back("READOUTS", m_currentExpInfo.readoutStart.toString("yyyy-MM-ddThh:mm:ss.zzz").toStdString());
        keywords.emplace_back("EXPTIME", QString::number(expTime, 'f', 3).toStdString());

        LOG_CAMERA(QString("添加时间戳到FITS头: EXPSTART=%1, EXPEND=%2, READOUTS=%3, EXPTIME=%4")
                       .arg(m_currentExpInfo.expStart.toString("yyyy-MM-dd hh:mm:ss.zzz"))
                       .arg(m_currentExpInfo.expEnd.toString("yyyy-MM-dd hh:mm:ss.zzz"))
                       .arg(m_currentExpInfo.readoutStart.toString("yyyy-MM-dd hh:mm:ss.zzz"))
                       .arg(expTime));
    }

    // 使用Python脚本转换
    QProcess process;
    QString python = "/home/csst/anaconda3/bin/python3";
    QString script = "/home/csst/PS_mosaic/tmp/bin2fits_250522.py";
    QString fitsFile = QString("%1/%2_%3.fits").arg(fitsSavePath).arg(currentBaseFilename).arg(tag);

    process.start(python, {script, binFile, fitsSavePath, currentBaseFilename});

    if (!process.waitForFinished(50000)) {
        LOG_CAMERA("转换超时");
    } else if (process.exitCode() != 0) {
        LOG_CAMERA(process.readAllStandardError());
    } else {
        LOG_CAMERA("转换成功: " + fitsFile);
        QString fitsName = QString("%1_%2.fits").arg(currentBaseFilename).arg(tag);
        recordShootingHistory(fitsName, fitsSavePath); // 记录历史
        
        // added by XYH@20250804, 利用全局变量fitsDone[0,1,2,3]来判断是不是所有4个fits都转换成功

        // 如果转换成功，更新FITS头信息
        //if (m_currentExpInfo.isValid() && m_currentExpInfo.tag == tag) {
        if (m_currentExpInfo.isValid()) {
            QJsonObject headerObj;
            for (const auto& keyword : keywords) {
                headerObj.insert(QString::fromStdString(keyword.first),
                                 QString::fromStdString(keyword.second));
            }

            // 在后台线程中更新FITS头
            QtConcurrent::run([this, fitsFile, headerObj]() {
                updateFitsHeader(fitsFile, headerObj);
            });
        }

        // 如果是序列拍摄模式，则继续下一个任务
        if (isSequenceRunning && (QString("00") == tag)) {
            QTimer::singleShot(5000, this, &MainWindow::processSequenceNextFrame);
        }
    }
    resetFrameCounter();
}*/
//python
void MainWindow::handleFrameDone(const QString &response)
{
    QStringList parts = response.split(':');
    QString tag;

    foreach (const QString &part, parts) {
        if (part.startsWith("done=")) {
            tag = part.mid(5);
            break;
        }
    }

    if (tag.isEmpty()) {
        LOG_CAMERA(" Invalid task ID");
        return;
    }

    // 记录收到的tag
    m_receivedTags.insert(tag);

    binPath = "/home/csst/PS_mosaic/data/bin_tmp";
    QString binFile = QString("%1/%2.bin").arg(binPath).arg(tag);
    //QString fitsFile = QString("%1/%2.fits").arg(fitsSavePath).arg(tag);

    std::vector<std::pair<std::string, std::string>> keywords = collectManualHeaderInfo();

    // 如果当前曝光信息匹配，添加时间戳关键字
    if (m_currentExpInfo.isValid()) {
        // 计算曝光时间（秒）
        double expTime = m_currentExpInfo.expStart.msecsTo(m_currentExpInfo.expEnd) / 1000.0;

        // 添加时间戳关键字
        keywords.emplace_back("TEMP", QString::number(hwStatus.currentTemp).toStdString());
        keywords.emplace_back("VACCUM", QString::number(hwStatus.currentVacuum, 'e', 3).toStdString());
        keywords.emplace_back("EXPSTART", m_currentExpInfo.expStart.toString("yyyy-MM-ddThh:mm:ss.zzz").toStdString());
        keywords.emplace_back("EXPEND", m_currentExpInfo.expEnd.toString("yyyy-MM-ddThh:mm:ss.zzz").toStdString());
        keywords.emplace_back("READOUTS", m_currentExpInfo.readoutStart.toString("yyyy-MM-ddThh:mm:ss.zzz").toStdString());
        keywords.emplace_back("EXPTIME", QString::number(expTime, 'f', 3).toStdString());



        LOG_CAMERA(QString("ADD TO FITS HEADER: EXPSTART=%1, EXPEND=%2, READOUTS=%3, EXPTIME=%4")
                       .arg(m_currentExpInfo.expStart.toString("yyyy-MM-dd hh:mm:ss.zzz"))
                       .arg(m_currentExpInfo.expEnd.toString("yyyy-MM-dd hh:mm:ss.zzz"))
                       .arg(m_currentExpInfo.readoutStart.toString("yyyy-MM-dd hh:mm:ss.zzz"))
                       .arg(expTime));
    }

    // 使用Python脚本转换
    QProcess process;
    QString python = "/home/csst/anaconda3/bin/python3";
    QString script = "/home/csst/PS_mosaic/tmp/bin2fits_250522.py";
    QString fitsFile = QString("%1/%2_%3.fits").arg(fitsSavePath).arg(currentBaseFilename).arg(tag);

    process.start(python, {script, binFile, fitsSavePath, currentBaseFilename});

    if (!process.waitForFinished(50000)) {
        LOG_CAMERA("Conversion timed out");
    } else if (process.exitCode() != 0) {
        LOG_CAMERA(process.readAllStandardError());
    } else {
        LOG_CAMERA("Conversion successfully: " + fitsFile);
        QString fitsName = QString("%1_%2.fits").arg(currentBaseFilename).arg(tag);
        recordShootingHistory(fitsName, fitsSavePath); // 记录历史

        // 如果转换成功，更新FITS头信息
        //if (m_currentExpInfo.isValid() && m_currentExpInfo.tag == tag) {
        if (m_currentExpInfo.isValid()) {
            QJsonObject headerObj;
            for (const auto& keyword : keywords) {
                headerObj.insert(QString::fromStdString(keyword.first),
                                 QString::fromStdString(keyword.second));
            }


            // 在后台线程中更新FITS头
            QtConcurrent::run([this, fitsFile, headerObj]() {
                updateFitsHeader(fitsFile, headerObj);
            });
        }
        if( !m_currentExpInfo.isManual && m_pendingResponse.isValid() && m_receivedTags.size() == 4){

            QString doneResponse = QString(
                                       "<ID=302><CamID=%1><TIME=%2><SHUTSTA=closed>"
                                       "<EXPST_TIME=%3><CUR_TEM=%4><INFO=OK><ACTION=DONE>"
                                       "<SENDTIME=%5><FITS_Name=%6>;")
                                       .arg(m_pendingResponse.camId)
                                       .arg(m_pendingResponse.expTime, 0, 'f', 2)
                                       .arg(m_pendingResponse.expStartTimeStr)
                                       .arg(hwStatus.currentTemp, 0, 'f', 2)
                                       .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz"))
                                       .arg(m_pendingResponse.imageName);

            sendResponse(doneResponse, m_pendingResponse.client);
            LOG_CAMERA(QString("Remote Exp completed. [Cam:%1][Tag:%2]").arg(m_pendingResponse.camId).arg(tag));
            // 清空已接收的tag
            m_receivedTags.clear();


            // 等待数据发送完成后优雅关闭
            m_pendingResponse.client->disconnectFromHost();

            // 让 Qt 自动在断开后释放资源
            connect(m_pendingResponse.client, &QTcpSocket::disconnected, m_pendingResponse.client, &QObject::deleteLater);

        }


        // 如果是序列拍摄模式，则继续下一个任务
        // if (isSequenceRunning && (QString("00") == tag)) {
        //     QTimer::singleShot(5000, this, &MainWindow::processSequenceNextFrame);
        // }
    }
    resetFrameCounter();
}

void MainWindow::processSequenceNextFrame(){

    LOG_GENERAL(QString("进入processSequenceNextFrame函数，当前连续拍摄序列为 [%1]，共%2个任务").arg(currentSequenceName).arg(sequenceTasks.size()));

    if (!isSequenceRunning || ++currentSequenceIndex >= sequenceTasks.size()) {
        // 序列完成
        LOG_GENERAL("连续拍摄序列已完成");
        sequenceFinished(); // 发射完成信号
        progressTimer->stop();
        ui->labelProgressStatus->setText("序列完成");
        ui->btnStartExposure->setEnabled(true); // added by XYH @ 20250527
        return;
    }

    const SequenceTask &task = sequenceTasks[currentSequenceIndex];

    // 设置基础文件名
    currentBaseFilename = task.filename;
    ui->lineEditBaseFilename->setText(currentBaseFilename);

    // 更新UI显示当前进度
    /*
    ui->labelSequenceProgress->setText(
        QString("正在拍摄: %1/%2 - %3")
            .arg(currentSequenceIndex + 1)
            .arg(sequenceTasks.size())
            .arg(currentBaseFilename)
        );*/

    // 设置曝光参数
    // LOG_GENERAL(QString("@@@@@ expTime: %1 s").arg(task.expTime));

    ui->doubleSpinBoxExposureTime->setValue(task.expTime);
    //ui->checkBoxDarkFrame->setChecked(task.dark);
    ui->checkBoxPinning->setChecked(task.pinning);
    ui->checkBoxDump->setChecked(task.dump);

    // 开始曝光
    on_btnStartExposure_clicked();
    LOG_GENERAL(QString("开始序列任务 %1/%2").arg(currentSequenceIndex+1).arg(sequenceTasks.size()));
}


